package tbquestion_client.form;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import chat.ChatMessage;
import chat.TextChatMessage;
import chat.sound.SoundFocusListener;
import fsktms.request.IRequestDelegate;
import fsktms.request.Request;
import fsktms.request.RequestParameters;
import fsktms.request.RequestRespond;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.text.DefaultCaret;
import model.ClientModel;
import model.StringListModel;
import model.chat.ChatMessageModel;
import qclient.QClient;

/**
 *
 * @author Mrkupi
 */
public class worldChat extends javax.swing.JFrame implements ListDataListener, SoundFocusListener
{
    /**
     * Creates new form worldChat
     */
    private String roomID = "0";
    private String roomName = "World Chat";
    private ChatMessageModel messageModel;
    
    public worldChat() 
    {
        initComponents();
        setLocation( 400, 200 );
        
        windowInitCustomize();
        loginToServerChat();
        loadUserInfo();
        loadHistoryMessages();
        loadRooms();
    }

    private void windowInitCustomize()
    {
        taChatBox.setWrapStyleWord(true);
        DefaultCaret dc = (DefaultCaret) taChatBox.getCaret();
        dc.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
    }

    @Override
    public void dispose(){
        if (roomID.equals(ClientModel.getInstance().getSoundChatManager().getFocusID()))
        {
            ClientModel.getInstance().getSoundChatManager().setFocusID(null, false);
        }
        ClientModel.getInstance().getSoundChatManager().getListeners().remove(this);
        if (this.messageModel != null)
        {
            this.messageModel.removeListDataListener(this);
        }
        super.dispose();
    }
    
    private void loginToServerChat()
    {
        ClientModel.getInstance().getSoundChatManager().getListeners().add(this);
        try
        {
            RequestParameters params = new RequestParameters()
                    .set(RequestParameters.KEY_FUNCTION, "joinRoom")
                    .set("RoomID", this.roomID)
                    .set("UserID", ClientModel.getInstance().getAccount().getUserID());
            
            QClient.getInstance().getRequestManager().sendRequest(new Request(
                    "Chat", params, new IRequestDelegate() {

                @Override
                public void requestCompleted(RequestRespond respond) {
                }
            }));
        } catch (IOException ex) {
            Logger.getLogger(worldChat.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private void loadHistoryMessages()
    {
        try
        {
        System.out.println("Begin load history message");
            RequestParameters params = new RequestParameters()
                    .set(RequestParameters.KEY_FUNCTION, "getHistoryMessage")
                    .set("ReceiverID", this.roomID);
            final worldChat copyThis = this;
            QClient.getInstance().getRequestManager().sendRequest(new Request(
                    "Chat", params, new IRequestDelegate() {

                @Override
                public void requestCompleted(RequestRespond respond) {
                    if (respond.isSuccess())
                    {
                        ArrayList<TextChatMessage> messages = (ArrayList<TextChatMessage>) respond.getResult();
                        messageModel = new ChatMessageModel(messages);
                        messageModel.addListDataListener(copyThis);
                        ClientModel.getInstance().getMessageModels().put(roomID, messageModel);
                        copyThis.reloadAllMessages();
                        System.out.println("End load history messages");
                    }
                }
            }));
        } catch (IOException ex) {
            Logger.getLogger(worldChat.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private void loadUserInfo()
    {
        this.lblNickname.setText( ClientModel.getInstance().getAccount().getUserName() );
        this.lblExp.setText( String.valueOf( ClientModel.getInstance().getAccount().getExp() ) );
        this.lblLevel.setText( String.valueOf( ClientModel.getInstance().getAccount().getLevel() ) );
    }

    private void loadRooms() {
        try
        {
            RequestParameters params = new RequestParameters()
                    .set(RequestParameters.KEY_FUNCTION, "getAllRoomDescription");
            final worldChat copyThis = this;
            QClient.getInstance().getRequestManager().sendRequest(new Request(
                    "Chat", params, new IRequestDelegate() {

                @Override
                public void requestCompleted(RequestRespond respond) {
                    if (respond.isSuccess())
                    {
                        ArrayList<String> roomDescs = (ArrayList<String>) respond.getResult();
                        lstRooms.setModel(new StringListModel(roomDescs));
                    }
                }
            }));
        } catch (IOException ex) {
            Logger.getLogger(worldChat.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jLabel2 = new javax.swing.JLabel();
        pnInfo = new javax.swing.JPanel();
        jLabel4 = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        lblLevel = new javax.swing.JLabel();
        lblExp = new javax.swing.JLabel();
        lblNickname = new javax.swing.JLabel();
        jButton1 = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        taChatBox = new javax.swing.JTextArea();
        tfChat = new javax.swing.JTextField();
        btEnter = new javax.swing.JButton();
        jLabel3 = new javax.swing.JLabel();
        btCreateRoom = new javax.swing.JButton();
        tfRoomID = new javax.swing.JTextField();
        btJoinRoom = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        lstRooms = new javax.swing.JList();
        jLabel1 = new javax.swing.JLabel();
        btnSound = new javax.swing.JButton();

        jLabel2.setText("jLabel2");

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("WORLD CHAT");

        pnInfo.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        jLabel4.setText("Level");

        jLabel5.setText("Exp");

        jLabel6.setText("Nick name");

        lblLevel.setText("jLabel8");

        lblExp.setText("jLabel8");

        lblNickname.setText("jLabel8");

        jButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/popo_emotions_full_version boss copy.png"))); // NOI18N
        jButton1.setToolTipText("");

        javax.swing.GroupLayout pnInfoLayout = new javax.swing.GroupLayout(pnInfo);
        pnInfo.setLayout(pnInfoLayout);
        pnInfoLayout.setHorizontalGroup(
            pnInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnInfoLayout.createSequentialGroup()
                .addGroup(pnInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(pnInfoLayout.createSequentialGroup()
                        .addGap(35, 35, 35)
                        .addComponent(jLabel4)
                        .addGap(10, 10, 10)
                        .addComponent(lblLevel))
                    .addGroup(pnInfoLayout.createSequentialGroup()
                        .addGap(42, 42, 42)
                        .addComponent(jLabel5)
                        .addGap(10, 10, 10)
                        .addComponent(lblExp))
                    .addGroup(pnInfoLayout.createSequentialGroup()
                        .addGap(12, 12, 12)
                        .addComponent(jLabel6)
                        .addGap(10, 10, 10)
                        .addComponent(lblNickname))
                    .addGroup(pnInfoLayout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 110, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        pnInfoLayout.setVerticalGroup(
            pnInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnInfoLayout.createSequentialGroup()
                .addGap(13, 13, 13)
                .addComponent(jButton1)
                .addGap(8, 8, 8)
                .addGroup(pnInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel4)
                    .addComponent(lblLevel))
                .addGap(6, 6, 6)
                .addGroup(pnInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel5)
                    .addComponent(lblExp))
                .addGap(6, 6, 6)
                .addGroup(pnInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel6)
                    .addComponent(lblNickname)))
        );

        taChatBox.setEditable(false);
        taChatBox.setColumns(20);
        taChatBox.setRows(5);
        taChatBox.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        jScrollPane1.setViewportView(taChatBox);

        tfChat.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                onEnter_pressed(evt);
            }
        });

        btEnter.setText("Enter");
        btEnter.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                onEnter_clicked(evt);
            }
        });

        jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel3.setText("ROOM");
        jLabel3.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        jLabel3.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);

        btCreateRoom.setText("Create Room");
        btCreateRoom.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btCreateRoomActionPerformed(evt);
            }
        });

        btJoinRoom.setText("Join Room");
        btJoinRoom.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btJoinRoomActionPerformed(evt);
            }
        });

        lstRooms.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                roomList_onClicked(evt);
            }
        });
        jScrollPane2.setViewportView(lstRooms);

        jLabel1.setText("Room Name");

        btnSound.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/voice-support copy.png"))); // NOI18N
        btnSound.setText("Sound: Mute");
        btnSound.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnSoundActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(21, 21, 21)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(pnInfo, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(btnSound, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addGap(26, 26, 26)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 343, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(tfChat, javax.swing.GroupLayout.DEFAULT_SIZE, 372, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
                    .addComponent(tfRoomID)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(btEnter, javax.swing.GroupLayout.PREFERRED_SIZE, 66, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 66, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGap(0, 0, Short.MAX_VALUE))
                    .addComponent(btCreateRoom, javax.swing.GroupLayout.DEFAULT_SIZE, 174, Short.MAX_VALUE)
                    .addComponent(btJoinRoom, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(39, 39, 39)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabel3)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 211, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(13, 13, 13)
                        .addComponent(jLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(tfRoomID, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btCreateRoom)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btJoinRoom))
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 345, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(pnInfo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(btnSound, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 36, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(tfChat, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(btEnter))
                .addGap(26, 26, 26))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void onEnter_pressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_onEnter_pressed
        if( evt.getKeyCode() == java.awt.event.KeyEvent.VK_ENTER )
            sendMessageToAllPeople();
    }//GEN-LAST:event_onEnter_pressed

    private void onEnter_clicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_onEnter_clicked
        sendMessageToAllPeople();
    }//GEN-LAST:event_onEnter_clicked

    private void btCreateRoomActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btCreateRoomActionPerformed
//        createWorldChat( Integer.parseInt(tfRoomID.getText()) );
    }//GEN-LAST:event_btCreateRoomActionPerformed

    private void btJoinRoomActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btJoinRoomActionPerformed
        openRoomChat(tfRoomID.getText());
    }//GEN-LAST:event_btJoinRoomActionPerformed

    private void roomList_onClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_roomList_onClicked
        if(evt.getClickCount() == 2)
        {
            String roomDescs = (String) lstRooms.getSelectedValue();
            if (roomDescs != null)
            {
                String _roomID = roomDescs.split(":")[0];
                ClientModel.getInstance().getForms().showChatForm(_roomID, ClientForms.CHATFORM_ROOM);
            }
        }
    }//GEN-LAST:event_roomList_onClicked

    private void btnSoundActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSoundActionPerformed
        // TODO add your handling code here:
        if (roomID.equals(ClientModel.getInstance().getSoundChatManager().getFocusID()))
        {
            ClientModel.getInstance().getSoundChatManager().setFocusID(null, false);
        }
        else
        {
            ClientModel.getInstance().getSoundChatManager().setFocusID(roomID, false);
        }
    }//GEN-LAST:event_btnSoundActionPerformed

    private boolean sendMessageToAllPeople()
    {
        if( !makeSureNotEmptyTextField() )
            return false;
        try
        {
            String msgContent = this.tfChat.getText();
            this.tfChat.setText(null);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            TextChatMessage chatMsg = new TextChatMessage(
                    ClientModel.getInstance().getAccount().getUserID(),
                    roomID,
                    msgContent);
            oos.writeObject(chatMsg);
            QClient.getInstance().getNetClient().sendMessage(bos.toByteArray(), 
                    ChatMessage.CHAT_MESSAGE_MAGICKEY);
            this.messageModel.addMessage(chatMsg);
        }
        catch (IOException ex)
        {
            
        }
        
        return false;
    }
    
    private boolean makeSureNotEmptyTextField()
    {
        if( "".equals( tfChat.getText() ))
        {
            JOptionPane.showMessageDialog( this, "" );
            return false;
        }
        return true;
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btCreateRoom;
    private javax.swing.JButton btEnter;
    private javax.swing.JButton btJoinRoom;
    private javax.swing.JButton btnSound;
    private javax.swing.JButton jButton1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JLabel lblExp;
    private javax.swing.JLabel lblLevel;
    private javax.swing.JLabel lblNickname;
    private javax.swing.JList lstRooms;
    private javax.swing.JPanel pnInfo;
    private javax.swing.JTextArea taChatBox;
    private javax.swing.JTextField tfChat;
    private javax.swing.JTextField tfRoomID;
    // End of variables declaration//GEN-END:variables

    @Override
    public void intervalAdded(ListDataEvent e) {
        for (int i = e.getIndex0(); i < e.getIndex1(); ++i)
        {
            TextChatMessage chatMsg = (TextChatMessage) messageModel.getElementAt(i);
            this.appendMessage(chatMsg);
        }
    }

    @Override
    public void intervalRemoved(ListDataEvent e) {
        this.reloadAllMessages();
    }

    @Override
    public void contentsChanged(ListDataEvent e) {
        this.reloadAllMessages();
    }
    
    private void appendMessage(TextChatMessage chatMsg)
    {
        this.taChatBox.append(chatMsg + "\n");
        System.out.println("Append message " + chatMsg);
    }
    
    private void reloadAllMessages()
    {
        System.out.println("Reload all messages, nMessage " + messageModel.getSize());
        this.taChatBox.setText(null);
        for (int i = 0; i < messageModel.getSize(); ++i)
        {
            TextChatMessage chatMsg = (TextChatMessage) messageModel.getElementAt(i);
            this.appendMessage(chatMsg);
        }
        System.out.println("Reload all messages completed");
    }

    private void openRoomChat(String roomID)
    {
        ClientModel.getInstance().getForms().showChatForm(roomID, ClientForms.CHATFORM_ROOM);
    }    

    @Override
    public void onFocusChanged(String focus, String oldFocus)
    {
        if (roomID.equals(focus))   // has focus
        {
            this.btnSound.setText("Sound: Listen");
            this.sendListen();
        }
        else    // no focus
        {
            if (roomID.equals(oldFocus))    // lost focus
            {
                this.sendMute();
            }
            
            this.btnSound.setText("Sound: Muted");
        }
    }

    @Override
    public void becomeTalker(String talkerID) {
        this.btnSound.setText("Sound: Talk");
        ClientModel.getInstance().getSoundChatManager().startRecord();
    }
    
    private void sendListen()
    {
        try
        {
            RequestParameters params = new RequestParameters()
                    .set(RequestParameters.KEY_FUNCTION, "listenRoom")
                    .set("RoomID", this.roomID)
                    .set("UserID", ClientModel.getInstance().getAccount().getUserID());
            final worldChat copyThis = this;
            QClient.getInstance().getRequestManager().sendRequest(new Request(
                    "Chat", params, new IRequestDelegate() {

                @Override
                public void requestCompleted(RequestRespond respond) {
                    if (respond.isSuccess())
                    {
                    }
                }
            }));
        } catch (IOException ex) {
            Logger.getLogger(worldChat.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private void sendMute()
    {
        try
        {
            RequestParameters params = new RequestParameters()
                    .set(RequestParameters.KEY_FUNCTION, "muteRoom")
                    .set("RoomID", this.roomID)
                    .set("UserID", ClientModel.getInstance().getAccount().getUserID());
            final worldChat copyThis = this;
            QClient.getInstance().getRequestManager().sendRequest(new Request(
                    "Chat", params, new IRequestDelegate() {

                @Override
                public void requestCompleted(RequestRespond respond) {
                    if (respond.isSuccess())
                    {
                    }
                }
            }));
        } catch (IOException ex) {
            Logger.getLogger(worldChat.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
